<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Hello Three.js</title>
  <style>
    body {
      margin: 0;
    }

    canvas {
      width: 100%;
      height: 100%;
      display: block;
    }
  </style>
</head>

<body onload="init()">
  <!-- onload比ready执行的晚一点 -->

  <script src="https://cdn.bootcdn.net/ajax/libs/three.js/r128/three.js"></script>
  <script src="https://cdn.bootcdn.net/ajax/libs/stats.js/r9/Stats.min.js"></script>
  <script src="https://cdn.bootcdn.net/ajax/libs/dat-gui/0.7.7/dat.gui.min.js"></script>
  <script>
    // 声明一些全局变量
    var renderer, camera, scene, geometry, material, mesh;

    // 性能插件，监听fps
    var stats = new Stats();
    console.log(stats.getDomElement());
    document.body.appendChild(stats.getDomElement());
    stats.getDomElement().style.position = 'absolute';

    // 初始化渲染器
    function initRenderer() {
      renderer = new THREE.WebGLRenderer(); // 实例化渲染器
      renderer.setSize(window.innerWidth, window.innerHeight); // 设置宽和高
      document.body.appendChild(renderer.domElement); // 添加到dom
    }

    // 初始化场景
    function initScene() {
      scene = new THREE.Scene(); // 实例化场景
    }

    // 初始化相机
    function initCamera() {
      // 视野、宽高比、近截面、远截面
      camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 200); // 实例化相机
      camera.position.set(0, 0, 15); // x, y, z
    }

    // 创建模型
    function initMesh() {
      geometry = new THREE.BoxGeometry(2, 2, 2); // 创建几何体
      material = new THREE.MeshNormalMaterial(); // 创建材质
      mesh = new THREE.Mesh(geometry, material); // 创建网格
      mesh.name = 'lft';
      // 隐藏 3d 模型
      // mesh.visible = false;
      scene.add(mesh); // 将网格添加到场景
    }

    // 运行动画
    function animate() {
      requestAnimationFrame(animate); // 循环调用函数
      mesh.rotation.x += 0.01; // 毎帧网格模型的沿 X轴旋转0.01弧度
      mesh.rotation.y += 0.02; // 毎帧网格模型的沿 y轴旋转0.02弧度
      stats.update();
      renderer.render(scene, camera); // 渲染界面
    }

    // 使用 dat-gui 调试工具
    let controls = {
      positionX: 0,
      positionY: 0,
      positionZ: 0,
    }

    // 初始化函数，页面加载完成后调用
    function init() { // 3D三要素
      initRenderer(); // 渲染
      initScene(); // 场景
      initCamera(); // 相机

      initMesh(); // 物体
      animate(); // 旋转，动画

      let gui = new dat.GUI(); // 实例化
      gui.add(controls, 'positionX', -5, 5).onChange(updatePosition);
      gui.add(controls, 'positionY', -5, 5).onChange(updatePosition);
      gui.add(controls, 'positionZ', -5, 5).onChange(updatePosition);

      function updatePosition() {
        mesh.position.set(controls.positionX, controls.positionY, controls.positionZ);
      }


      // renderer, camera, scene, geometry, material, mesh
      /* 
        THREE.Object3D：
          Three.js将每个能够直接添加到场景的对象都继承自一个基类：THREE.Object3D
          我们将继承自这个基类的对象成为 3D 对象，判断一个对象是否继承自 THREE.Object3D
          我们使用以下方法
      */
      console.log('renderer', renderer instanceof THREE.Object3D);
      console.log('camera', camera instanceof THREE.Object3D);
      console.log('scene', scene instanceof THREE.Object3D);
      console.log('geometry', geometry instanceof THREE.Object3D);
      console.log('material', material instanceof THREE.Object3D);
      console.log('mesh', mesh instanceof THREE.Object3D);

      /* 
        获取一个3D对象
        Object3D.name = 'firstName';
        scene.add(Object3D)
        scene.getChildByName("firstName"); //返回第一个匹配的3D对象
      */
      console.log(scene.getChildByName('lft'));

      /* 
        隐藏一个3D对象
        mesh.visible = false; 
        删除一个3D对象
        scene.remove(mesh);
      */

      /* 
        修改位置的3种方式：
        1、单独设置
          mesh.position.x = 3;
          mesh.position.y += 3;
          mesh.position.z -= 3;
        
        2、一次性设置所有：
        mesh.position.set(3, 5, -6);

        3、通过THREE.Vector3()三维向量
        mesh.position = new THREE.Vector3(3, 5, -6);
      */

      /* 
        修改大小：
        1、单独设置：
          mesh.scale.x = 2; //模型沿x轴放大一倍
          mesh.scale.y = 0.5; //模型沿y轴缩小一倍
          mesh.scale.z = 1; //模型沿z轴保持不变

        2、使用set方法：
          mesh.scale.set(2, 2, 2);

        3、使用三维向量
          mesh.scale = new THREE.Vector3(2, 2, 2);
      */

      /* 
        修改模型的转向（同上也是3种方式）
          mesh.rotation.x += 0.01; // 毎帧网格模型的沿 X轴旋转0.01弧度
          mesh.rotation.y += 0.02;
      */
    }







  </script>

</body>

</html>